Athena の利用料金が気になったので AWS WAF ログ分析にパーティションを使ってみた
みなさま Xin chao !
ここ最近、new AWS WAF (=AWS WAF v2 と表記される場合もありますが以降 AWS WAF と表記します) で試行錯誤しています。
先日のアップデートにより、AWS 製のマネージドルールの提供も開始され、AWS WAF をこれまで以上に手軽に利用することができるようになったのではないかと思います。
AWS WAF 用 AWS Managed Rules の発表 - Amazon Web Services ブログ
[アップデート] AWS WAF向けAWS製のManaged Rulesが出ました - Developers.IO
AWS 製のマネージドルールを適用した際に、どの程度検知してくれるかを確認している中で、弊社ブログを参考に Athena で AWS WAF のログを確認していたのですが、大量のログが記録される実運用環境では、スキャンされたデータ量で課金される Athena の利用料金が気になってしまうのではないか? と思いました。
そこで、Athena で AWS WAF のログ分析を行う際、パーティションを定義して、スキャンされる AWS WAF のログのデータ量を年・月で絞ることを試してみました。
パーティションについては、以下の弊社ブログが参考になります。
Athena でテーブルを作成する
まずは以下の弊社ブログをもとに、Athena でテーブルを作成していきますが、パーティション定義用に 1 行追加します。
追加するのは、以下の 5 行目です。
CREATE EXTERNAL TABLE IF NOT EXISTS waflogs ( ~~~~~ 中略 ~~~~~ ) PARTITIONED BY (year int, month int) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' LOCATION 's3://[バケット名]/';
なお、パーティションを使用しない場合、テーブルを作成した時点から AWS WAF のログを検索することができますが、パーティションを使用する場合は、以下に続くパーティションの追加を行わないと、ログが検索対象となりませんでした。
パーティションを追加する
今回使用しているテスト環境には、2020/1/21 と 2020/3/9 のログが記録されているので、まずは 2020 年 1 月のパーティションを追加します。 [バケット名] は AWS WAF のログを保管している S3 バケットを指定します。
ALTER TABLE waflogs ADD IF NOT EXISTS PARTITION (year=2020, month=1) location 's3://[バケット名]/2020/01/';
続いて 2020 年 3 月のパーティションを追加します。
ALTER TABLE waflogs ADD IF NOT EXISTS PARTITION (year=2020, month=3) location 's3://[バケット名]/2020/03/';
もしそれ以外の年月のログが存在する場合は、同様に 1 カ月づつ追加する必要があります。
パーティションの追加状況を確認する
パーティションが正しく追加されたことを確認します。
SHOW PARTITIONS waflogs;
以下の通り、正しく追加されていることが確認できました。
year=2020/month=1 year=2020/month=3
スキャンされるデータ量の違いを確認してみる
まずは全件検索した場合に、どれだけのデータがスキャンされるか試します。
SELECT from_unixtime(timestamp/1000, 'Asia/Tokyo') AS JST, * FROM waflogs ORDER BY timestamp DESC;
テスト環境のためデータ総数が少ないですが、2.64 KB のデータがスキャンされました。
続いて 2020 年 1 月に限定してログを検索します。
SELECT from_unixtime(timestamp/1000, 'Asia/Tokyo') AS JST, * FROM waflogs WHERE year=2020 AND month=1 ORDER BY timestamp DESC;
スキャン対象は 2020 年 1 月のログのみになるため、0.98 KB のデータがスキャンされました。
2020 年 3 月に限定してログを検索します。
SELECT from_unixtime(timestamp/1000, 'Asia/Tokyo') AS JST, * FROM waflogs WHERE year=2020 AND month=3 ORDER BY timestamp DESC;
スキャン対象は 2020 年 3 月のログのみになるため、1.66 KB のデータがスキャンされました。
参考として、パーティションを定義していない場合も試してみました。 検索条件を日付で指定しても、全件検索した場合と同じデータ量がスキャンされます。
SELECT from_unixtime(timestamp/1000, 'Asia/Tokyo') AS JST, * FROM waflogs WHERE date(from_unixtime(timestamp/1000, 'Asia/Tokyo')) = date '2020-01-21' ORDER BY timestamp DESC;
後片付け
2020 年 1 月のパーティションを削除します。
ALTER TABLE waflogs DROP IF EXISTS PARTITION (year=2020, month=1);
同様に 2020 年 3 月のパーティションも削除します。 以下の通り、2020 年全部を削除することも可能です。
ALTER TABLE waflogs DROP IF EXISTS PARTITION (year=2020);
テーブルを削除します。
DROP TABLE waflogs;
S3 上に保存された Athena クエリー結果を削除し、後片付け終了です。
まとめ
AWS WAF のログ検索に Athena を使用する際、パーティションを使ってスキャン対象のデータ量を絞ってみました。 今回は年・月でスキャン対象を絞りましたが、年・月・日で絞ることも可能です。
Athena の利用料金とパフォーマンスはスキャン対象のデータ量に比例します。
今回試したテスト環境ではログの全体量が少ないため、パーティションを使う/使わないで利用料金の差はないのですが、ログ分析基盤が整備されていない中でセキュリティインシデント調査など急遽大量のログと格闘しなければならないような場合に、パーティションを活用していただければ想定外の Athena の利用料金にならなくて済むのではないかと思います。